#ifndef _GAME_OBJECT_
#define _GAME_OBJECT_

#include "aerial\Object\Object.h"
#include "aerial\Game\Helper\BattleHelper.h"
#include "aerial\Core\Acc.h"
#include <iostream>

#include "Box2D\Box2D.h"

using namespace air;
using namespace std;

struct ContactObject;
class AirContactListener;

#define TYPE_FLY	0x0
#define TYPE_WEAPON 0x1

/// @brief basic class for aircraft and weapon
class GameObject: public IObject {
	friend struct ContactObject;
	friend class AirContactListener;
public:
	static void SetWorld(b2World* _world);

	/// @brief construct using position and rotation
	GameObject(float x, float y, int id, float _rot = 0.f);

	/// @biref construct using position and direction vector
	GameObject(float x, float y, float dx, float dy, int id);
	virtual ~GameObject() { 
		if (world) world->DestroyBody(body);
	}

	virtual bool update(float dt);

	/// @brief position transform try to avoid for performance
	void SetTransform(float _x, float _y);

	/// @brief rotate dA positive for clockwise
	inline void Rotate(float dA)
	{
		A += dA;
		b2Rot a(A);
		A = a.GetAngle();
		D = -a.GetYAxis();
	}

	inline void SetRotate(float dA)
	{
		A = dA;
		b2Rot a(A);
		A = a.GetAngle();
		D = -a.GetYAxis();
	}

	inline void SetSpeed(const b2Vec2& _V) {	
		V = _V;	
		body->SetLinearVelocity(V);
	}
	
	virtual void RegulateDeviation();
	/// @brief transform Co-ordinate from Box2d to HGE
	inline void CoordinateTransform() 
	{  
		T = BattleHelper::getHgeCoordinateFromBox2d(body->GetPosition());
		V = body->GetLinearVelocity();
	}

	inline const b2Vec2& GetPosition()  { return T; }

	inline void SetDirection(const b2Vec2& _D)
	{
		D = _D;
		D.Normalize();
		A = atan2(D.x, -D.y);
		if (A < 0) A += b2_pi * 2;
	}

	inline float GetAngle() const { return A; }
	inline const b2Vec2& GetDirection() { return D; }
	inline const b2Vec2& GetSpeed() { return V; }
	inline virtual uchar GetObjectType() = 0;
	inline int GetID() const { return id; }
	inline b2Body* a_GetBody() { return body; }

	virtual void Die()
	{
		body->SetType(b2_staticBody);
	}

	bool toDestroy;
protected:
	/// @brief 2d vector to describe object's current position
	b2Vec2 T;
	/// @brief 2d vector to describe object's current direction synchronized with A
	b2Vec2 D;
	/// @brief velocity
	b2Vec2 V;
	/// @brief 2d vector to describe object's current angle synchronized with D
	float A;
	/// @brief speed = v * D;
	//float VScale;

	/// @brief pointer to object in Box2d
	b2Body* body;
	
	/// @brief remote Position deviation
	b2Vec2 remoteDevT;
	b2Vec2 remoteDevV;

	/// @brief remote Angle deviation
	float remoteDevA;

	float regulationTime;
	bool adjusted;

	static b2World* world;
	static const int MaxRegulationCount;
	/**
	 * @GameObject id unique will be assigned id less than or equal to 10. 
	 Weapon will be assigned id greater than 10;
	 MUST be initialized when the battlescene start
	 */
	uchar id;
private:
	void initialize();
	GameObject() {}
};

#endif